package com.weaving.monitor.controller;

import com.weaving.monitor.dto.*;
import com.weaving.monitor.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * 经编机监控控制器
 * 
 * 功能说明：
 * 1. 提供经编机监控相关的REST API接口
 * 2. 处理前端页面的HTTP请求
 * 3. 调用服务层处理业务逻辑
 * 4. 返回JSON格式的响应数据
 * 
 * 注解说明：
 * - @RestController: Spring注解，标识这是一个REST控制器，返回JSON数据
 * - @RequestMapping: 指定控制器的基础URL路径为"/api/monitor"
 * - @RequiredArgsConstructor: Lombok注解，自动生成包含final字段的构造函数
 * - @CrossOrigin: 允许跨域请求，支持前端页面访问
 * 
 * API接口说明：
 * 1. GET /api/monitor/machines - 获取所有机器状态
 * 2. GET /api/monitor/machines/{machineNumber} - 获取指定机器状态
 * 3. GET /api/monitor/machines/{machineNumber}/detail - 获取机器详细信息
 * 4. GET /api/monitor/pending-plans - 获取所有待翻品种计划
 * 
 * 依赖服务：
 * - MachineService: 经编机服务，处理机器相关业务逻辑
 * - PendingPlanService: 待翻品种计划服务，处理计划相关业务逻辑
 * - MachineDetailService: 机器详情服务，处理详细信息相关业务逻辑
 * 
 * @author 系统开发团队
 * @version 1.0
 * @since 2024-01-01
 */
@RestController
@RequestMapping("/api/monitor")
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
public class MonitorController {
    
    /** 经编机服务，通过构造函数注入 */
    private final MachineService machineService;
    
    /** 待翻品种计划服务，通过构造函数注入 */
    private final PendingPlanService pendingPlanService;
    
    /** 机器详情服务，通过构造函数注入 */
    private final MachineDetailService machineDetailService;
    
    /** 疵点查询服务，通过构造函数注入 */
    private final FlawQueryService flawQueryService;
    private final ProdTodayAmountExportService prodTodayAmountExportService;
    private final ProdTodayAmountExportOptimizedService prodTodayAmountExportOptimizedService;
    
    /**
     * 获取所有机器的状态信息
     * 
     * 功能说明：
     * 1. 提供获取所有机器状态的REST API接口
     * 2. 返回所有机器的基本信息，用于首页展示
     * 3. 支持前端页面的实时数据更新
     * 
     * 请求方式：GET
     * 请求路径：/api/monitor/machines
     * 响应格式：JSON数组，包含所有机器的状态信息
     * 
     * 使用场景：
     * - 首页机器状态展示
     * - 实时数据刷新
     * - 机器状态监控
     * 
     * @return 所有机器状态信息的列表
     */
    @GetMapping("/machines")
    public List<MachineStatusDto> getAllMachineStatus() {
        return machineService.getAllMachineStatus();
    }
    
    /**
     * 获取指定机器的状态信息
     * 
     * 功能说明：
     * 1. 根据机器号获取特定机器的状态信息
     * 2. 支持单个机器的详细信息查询
     * 3. 如果机器不存在则返回null
     * 
     * 请求方式：GET
     * 请求路径：/api/monitor/machines/{machineNumber}
     * 路径参数：machineNumber - 机器编号
     * 响应格式：JSON对象，包含指定机器的状态信息
     * 
     * 使用场景：
     * - 单个机器状态查询
     * - 机器详情页面数据获取
     * - 特定机器监控
     * 
     * @param machineNumber 机器编号，从URL路径中获取
     * @return 指定机器的状态信息，如果不存在则返回null
     */
    @GetMapping("/machines/{machineNumber}")
    public MachineStatusDto getMachineStatus(@PathVariable Integer machineNumber) {
        return machineService.getMachineStatus(machineNumber);
    }
    
    /**
     * 获取指定机器的详细信息
     * 
     * 功能说明：
     * 1. 根据机器号获取完整的机器详细信息
     * 2. 包含基本信息、订单详情、工艺信息、图表数据等
     * 3. 如果机器不存在则返回默认数据
     * 
     * 注意：此接口已被拆分为多个子接口以提高性能
     * 建议使用以下接口替代：
     * - /api/monitor/machines/{machineNumber}/basic - 基本信息
     * - /api/monitor/machines/{machineNumber}/charts - 图表数据
     * - /api/monitor/machines/{machineNumber}/defects - 疵点统计
     * - /api/monitor/machines/{machineNumber}/guide-bars - 梳栉详情
     * 
     * @param machineNumber 机器编号
     * @return 机器的详细信息，包含所有页面需要的数据
     * @deprecated 建议使用拆分后的接口以提高性能
     */
    @GetMapping("/machines/{machineNumber}/detail")
    @Deprecated
    public MachineDetailDto getMachineDetail(@PathVariable Integer machineNumber) {
        return machineDetailService.getMachineDetail(machineNumber);
    }
    
    /**
     * 获取指定机器的基本信息
     * 
     * 功能说明：
     * 1. 获取机器基本状态和订单信息
     * 2. 包含机器号、当前速度、材料类型、订单号等
     * 3. 响应速度快，适合频繁调用
     * 
     * @param machineNumber 机器编号
     * @return 机器基本信息
     */
    @GetMapping("/machines/{machineNumber}/basic")
    public MachineDetailDto getMachineBasicInfo(@PathVariable Integer machineNumber) {
        return machineDetailService.getMachineBasicInfo(machineNumber);
    }
    
    /**
     * 获取指定机器的图表数据
     * 
     * 功能说明：
     * 1. 获取订单完成进度、故障分布、时间图等图表数据
     * 2. 包含饼图、散点图、时间图等数据
     * 3. 数据量较大，建议按需调用
     * 
     * @param machineNumber 机器编号
     * @return 图表数据
     */
    @GetMapping("/machines/{machineNumber}/charts")
    public MachineDetailDto.ChartData getMachineChartData(@PathVariable Integer machineNumber) {
        return machineDetailService.getMachineChartData(machineNumber);
    }
    
    /**
     * 获取指定机器的疵点统计
     * 
     * 功能说明：
     * 1. 获取停车疵点和非停车疵点数量统计
     * 2. 基于当前生产卡片计算
     * 3. 数据量小，响应快速
     * 
     * @param machineNumber 机器编号
     * @return 疵点统计数据
     */
    @GetMapping("/machines/{machineNumber}/defects")
    public MachineDetailDto.DefectStats getMachineDefectStats(@PathVariable Integer machineNumber) {
        return machineDetailService.getMachineDefectStats(machineNumber);
    }
    
    /**
     * 获取指定机器的梳栉详情
     * 
     * 功能说明：
     * 1. 获取L1、L2、L3、L4梳栉的配置信息
     * 2. 包含梳栉编号和对应的盘头型号
     * 3. 数据量小，响应快速
     * 
     * @param machineNumber 机器编号
     * @return 梳栉详情信息
     */
    @GetMapping("/machines/{machineNumber}/guide-bars")
    public List<MachineDetailDto.GuideBarDetail> getMachineGuideBarDetails(@PathVariable Integer machineNumber) {
        return machineDetailService.getMachineGuideBarDetails(machineNumber);
    }
    
    /**
     * 获取所有待翻品种计划
     * 
     * 功能说明：
     * 1. 获取所有机器的待翻品种计划信息
     * 2. 返回按机器分组的计划数据
     * 3. 用于首页待翻品种计划表格展示
     * 
     * 请求方式：GET
     * 请求路径：/api/monitor/pending-plans
     * 响应格式：JSON对象，包含按机器分组的计划信息
     * 
     * 返回数据结构：
     * {
     *   "plans": {
     *     "1": { "1": "计划详情1", "2": "计划详情2", "3": "计划详情3" },
     *     "2": { "1": "计划详情1", "2": "计划详情2", "3": "计划详情3" }
     *   }
     * }
     * 
     * 使用场景：
     * - 首页待翻品种计划展示
     * - 生产计划管理
     * - 计划执行监控
     * 
     * @return 所有待翻品种计划信息
     */
    @GetMapping("/pending-plans")
    public PendingPlanDto getAllPendingPlans() {
        return pendingPlanService.getAllPendingPlans();
    }
    
    /**
     * 根据机器ID和状态查询疵点详情列表
     * 
     * 功能说明：
     * 1. 首先通过machine_id和status查询prod_prod_card表中正在生产的生产卡id
     * 2. 再通过生产卡id去prod_product表中status=1的生产品id列表
     * 3. 最后通过生产品id关联prod_flaw表查询time、position字段
     * 4. 返回生产卡对应的prod_flaw表中的清单
     * 
     * 请求方式：GET
     * 请求路径：/api/monitor/flaws
     * 请求参数：
     * - machineId: 机器ID，如"J001"
     * - cardStatus: 生产卡状态，如"1"表示正在生产（可选，默认为"1"）
     * 响应格式：JSON数组，包含疵点详情列表
     * 
     * 返回数据结构：
     * [
     *   {
     *     "time": "2024-01-01 10:30:00",
     *     "position": "位置信息",
     *     "productId": "P001",
     *     "cardId": "C001",
     *     "type": 0
     *   }
     * ]
     * 
     * 字段说明：
     * - time: 疵点发生时间
     * - position: 疵点位置
     * - productId: 生产品ID
     * - cardId: 生产卡ID
     * - type: 疵点类型，0表示停车疵点，非0表示非停车疵点
     * 
     * 使用场景：
     * - 疵点详情查询
     * - 生产质量监控
     * - 疵点统计分析
     * 
     * @param machineId 机器ID
     * @param cardStatus 生产卡状态，默认为"1"
     * @return 疵点详情列表
     */
    @GetMapping("/flaws")
    public List<FlawDetailDto> getFlawDetails(
            @RequestParam String machineId,
            @RequestParam(defaultValue = "1") String cardStatus) {
        return flawQueryService.queryFlawDetailsByMachineIdAndStatus(machineId, cardStatus);
    }
    
    /**
     * 根据机器ID查询当前正在生产的疵点详情列表
     * 
     * 功能说明：
     * 1. 查询指定机器当前正在生产的生产卡对应的疵点详情
     * 2. 默认查询状态为"1"的生产卡
     * 
     * 请求方式：GET
     * 请求路径：/api/monitor/flaws/{machineId}
     * 路径参数：machineId - 机器ID
     * 响应格式：JSON数组，包含疵点详情列表
     * 
     * @param machineId 机器ID
     * @return 疵点详情列表
     */
    @GetMapping("/flaws/{machineId}")
    public List<FlawDetailDto> getCurrentFlawDetails(@PathVariable String machineId) {
        return flawQueryService.queryCurrentFlawDetailsByMachineId(machineId);
    }

    @GetMapping("/prod-today-amount/excelold")
    public ResponseEntity<byte[]> exportProdTodayAmountExcel(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate) throws UnsupportedEncodingException {
        try {
            System.out.println("开始导出Excel，参数：startDate=" + startDate + ", endDate=" + endDate);

            LocalDate start = startDate != null ? LocalDate.parse(startDate) : LocalDate.now();
            LocalDate end = endDate != null ? LocalDate.parse(endDate) : start;

            System.out.println("解析后的日期：start=" + start + ", end=" + end);

            List<ProdTodayAmountExportDto> data = prodTodayAmountExportService.getExportData(start, end);
            System.out.println("查询到数据条数：" + data.size());

            if (data.isEmpty()) {
                System.out.println("没有查询到数据，返回空Excel文件");
                // 返回一个空的Excel文件而不是错误
                byte[] emptyExcel = prodTodayAmountExportService.generateExcelReport(new ArrayList<>());
                String fileName = "production_report_" + start.toString() + "_" + end.toString() + ".xlsx";
                return ResponseEntity.ok()
                        .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"")
                        .header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                        .body(emptyExcel);
            }

            byte[] excelContent = prodTodayAmountExportService.generateExcelReport(data);
            System.out.println("Excel文件生成成功，大小：" + excelContent.length + " 字节");

            String fileName = "production_report_" + start.toString() + "_" + end.toString() + ".xlsx";

            return ResponseEntity.ok()
                    .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"")
                    .header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                    .body(excelContent);
        } catch (Exception e) {
            System.err.println("导出Excel失败：" + e.getMessage());
            e.printStackTrace();
            // 返回错误信息而不是空的500响应
            String errorMessage = "Export failed: " + e.getMessage();
            return ResponseEntity.status(500)
                    .header("Content-Type", "text/plain; charset=utf-8")
                    .body(errorMessage.getBytes("UTF-8"));
        }
    }

    /**
     * 高效导出生产今日产量Excel报表（优化版）
     * 
     * 性能优化特性：
     * 1. 并行处理：使用CompletableFuture并行加载数据
     * 2. 批量查询：减少数据库访问次数
     * 3. 缓存优化：避免重复查询
     * 4. 流式处理：减少内存占用
     * 
     * 请求方式：GET
     * 请求路径：/api/monitor/prod-today-amount/excel-optimized
     * 请求参数：
     * - startDate: 开始日期（可选，格式：yyyy-MM-dd）
     * - endDate: 结束日期（可选，格式：yyyy-MM-dd）
     * 
     * 响应：Excel文件下载
     * 
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return Excel文件
     */
//    @GetMapping("/prod-today-amount/excel-optimized")
    @GetMapping("/prod-today-amount/excel")
    public ResponseEntity<byte[]> exportProdTodayAmountExcelOptimized(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate) throws UnsupportedEncodingException {
        
        long startTime = System.currentTimeMillis();
        
        try {
            System.out.println("开始优化导出Excel，参数：startDate=" + startDate + ", endDate=" + endDate);

            LocalDate start = startDate != null ? LocalDate.parse(startDate) : LocalDate.now();
            LocalDate end = endDate != null ? LocalDate.parse(endDate) : start;

            System.out.println("解析后的日期：start=" + start + ", end=" + end);

            // 使用优化服务获取数据
            List<ProdTodayAmountExportDto> data = prodTodayAmountExportOptimizedService.getExportDataOptimized(start, end);
            System.out.println("查询到数据条数：" + data.size());

            if (data.isEmpty()) {
                System.out.println("没有查询到数据，返回空Excel文件");
                byte[] emptyExcel = prodTodayAmountExportOptimizedService.generateExcelReportOptimized(new ArrayList<>());
                String fileName = "production_report_optimized_" + start.toString() + "_" + end.toString() + ".xlsx";
                return ResponseEntity.ok()
                        .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"")
                        .header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                        .body(emptyExcel);
            }

            // 使用优化服务生成Excel
            byte[] excelContent = prodTodayAmountExportOptimizedService.generateExcelReportOptimized(data);
            
            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;
            
            System.out.println("优化Excel文件生成成功，大小：" + excelContent.length + " 字节，耗时：" + duration + "ms");

            String fileName = "production_report_optimized_" + start.toString() + "_" + end.toString() + ".xlsx";

            return ResponseEntity.ok()
                    .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"")
                    .header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                    .header("X-Processing-Time", String.valueOf(duration))
                    .body(excelContent);
                    
        } catch (Exception e) {
            System.err.println("优化导出Excel失败：" + e.getMessage());
            e.printStackTrace();
            String errorMessage = "Optimized export failed: " + e.getMessage();
            return ResponseEntity.status(500)
                    .header("Content-Type", "text/plain; charset=utf-8")
                    .body(errorMessage.getBytes("UTF-8"));
        }
    }
} 